package org.example.handler;

import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * 模式类似struts2的prototype
 * 属于活久见的换汤不换药了
 *
 * @author zhangyf2595
 * @version 1.0
 * @date 2023/8/21
 **/

@Component
@ServerEndpoint("/websocket/{uid}")
@Slf4j
@EqualsAndHashCode
public class WebSocketHandler {
    private Session session;
    private String uid;
    // 保存当前Bean
    private static CopyOnWriteArraySet<WebSocketHandler> handlers = new CopyOnWriteArraySet<>();
    private static ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam(value = "uid") String uid) {
        try {
            this.session = session;
            this.uid = uid;
            handlers.add(this);
            sessions.put("uid", session);
            log.info("uid=[{}] connected, {} connection has been created.", uid, sessions.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnClose
    public void onClose() {
        try {
            handlers.remove(this);
            sessions.remove(this);
            log.info("uid=[{}] disconnected, {} connection remains.", uid, sessions.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @OnMessage
    public void onMessage(String message) {
        log.info("[{}] received.", message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }

    public void broadcast(String message) {
        log.info("[{}] has been broadcast.", message);
        for (WebSocketHandler socket : handlers) {
            if (!socket.session.isOpen()) {
                continue;
            }
            socket.session.getAsyncRemote().sendText(message);
        }
    }

    public void sendOnce(String uid, String message) {
        Session session = sessions.get(uid);
        if (session != null && session.isOpen()) {
            try {
                log.info("send single message=[{}]", message);
                session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void sendSome(String[] uids, String message) {
        for (String userId : uids) {
            Session session = sessions.get(userId);
            if (session != null && session.isOpen()) {
                try {
                    log.info("send single message=[{}]", message);
                    session.getAsyncRemote().sendText(message);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

}
